/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-13 13:40:05
 * @LastEditTime: 2021-08-09 15:17:50
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#include <string.h>
#include "kernel.h"
#include "timer_tacho.h"

#define MAX_32_VAL GENMASK(31, 0)
#define MAX_64_VAL GENMASK_ULL(63, 0)

typedef struct
{
    boolean     Bits32; //otherwise 64 bit
    boolean     RestartMode; //otherwise free-run
    boolean     CycCmp; //otherwise once cmp
    boolean     ClearCnt; //otherwise not clear
    boolean     ForceLoad; //otherwise not force-load
    boolean     StopTimer;
    u32         StartCnt;
    u32         CmpTick32;
    u64         CmpTick64;
    u32         StopCnt;
}TimerTestConfigs;

static TimerTachoCtrl timer; 
static const u32 timerId = 0;

void CycCmpHandler(void *pPara)
{
    TimerTachoCtrl *pCtrl = (TimerTachoCtrl *)pPara;
    printf("cyc cmp intr, timer id: %d", pCtrl->Config.Id);
}

void OnceCmpHandler(void *pPara)
{
    TimerTachoCtrl *pCtrl = (TimerTachoCtrl *)pPara;
    printf("once cmp intr, timer id: %d", pCtrl->Config.Id);    
}

void RolloverHandler(void *pPara)
{
    TimerTachoCtrl *pCtrl = (TimerTachoCtrl *)pPara;
    printf("roll over cmp intr, timer id: %d", pCtrl->Config.Id);      
}

void TimerFunctionTest(const TimerTestConfigs *pTest)
{
    u32 Ret = TIMER_SUCCESS;
    u32 CmpTick = MAX_32_VAL - (u32)0x1ffff;
    u64 CmpTick64 = MAX_64_VAL - (u64)0x1ffff;
    u32 StartTick = MAX_32_VAL - 0x2ffff;

    TimerTachoConfig *pConfig = &timer.Config;

    memset(&timer, 0, sizeof(timer));
    TimerGetDefConfig(timerId, pConfig);
    pConfig->WorkMode = TIMER_WORK_MODE_TIMER;

    if (pTest->RestartMode)
        pConfig->TimerMode = TIMER_RESTART;
    else
        pConfig->TimerMode = TIMER_FREE_RUN;

    pConfig->TimerBits = TIMER_32_BITS;

    if (pTest->CycCmp)
    {
        pConfig->CmpType = TIMER_CYC_CMP;
        TimerRegisterEvtCallback(&timer, TIMER_EVENT_CYC_CMP, CycCmpHandler);
    }
    else
    {
        pConfig->CmpType = TIMER_ONCE_CMP; 
        TimerRegisterEvtCallback(&timer, TIMER_EVENT_ONCE_CMP, OnceCmpHandler);
    }

    TimerRegisterEvtCallback(&timer, TIMER_EVENT_ROLL_OVER, RolloverHandler);

    pConfig->ClearCnt = pTest->ClearCnt;
    pConfig->ForceLoad = pTest->ForceLoad; 

    Ret  = TimerInit(&timer, pConfig);

    if (pTest->Bits32)
        Ret |= TimerSetPeriod32(&timer, CmpTick);
    else
        Ret |= TimerSetPeriod64(&timer, CmpTick64);
        
    TimerSetStartVal(&timer, StartTick);

    if (TIMER_SUCCESS == Ret)
    {
        TimerStart(&timer);
    }

    TimeSettingDump(&timer); 

    if (pTest->Bits32)
    {
        while (1)
        {
            printf("cur 32cnt: 0x%x", TimerGetCurCnt32(&timer));
        }          
    } 
    else
    {
        while (1)
        {
            printf("cur 64cnt: 0x%x", TimerGetCurCnt64(&timer));
        }         
    } 
}

#define TEST_CASE_1 \
{\
    .Bits32 = TRUE,\
    .RestartMode = TRUE,\
    .CycCmp = TRUE,\
    .ClearCnt = TRUE,\
    .ForceLoad = TRUE,\
    .StopTimer = FALSE,\
    .StartCnt = MAX_32_VAL - 0x2ffff,\
    .CmpTick32 = MAX_32_VAL - (u32)0x1ffff,\
    .CmpTick64 = MAX_64_VAL - (u64)0x1ffff,\
    .StopCnt = 0,   \
}

void TimerFunctionTestCases()
{
    TimerTestConfigs testCfg = TEST_CASE_1;
    TimerFunctionTest(&testCfg);
}